package org.twdata.pipeline.stage;

import java.io.StringWriter;
import java.io.Writer;
import javax.xml.transform.*;
import javax.xml.transform.sax.*;
import javax.xml.transform.stream.*;

// SAX imports:
import org.twdata.pipeline.*;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

/**
 *  Serializes SAX events to text by using Xalan. Can serialize as XML, HTML,
 *  and text.
 */
public class TextSerializer extends AbstractSerializer implements Serializer {

    private SAXTransformerFactory tfactory;
    private TransformerHandler handler = null;
    private String outputType;


    /**
     *  Initializes the serializer for the context.  Creates the transformer
     *  factory if hasn't been initialized.
     *
     *@param  ctx                    The context information
     *@exception  PipelineException  If something goes wrong
     */
    public void setup(PipelineContext ctx)
        throws PipelineException {
        try {
            if (tfactory == null) {
                tfactory = (SAXTransformerFactory) TransformerFactory.newInstance();
                tfactory.setErrorListener(new TraxErrorListener());
            }
            handler = tfactory.newTransformerHandler();
        } catch (Exception ex) {
            log.error(ex, ex);
            throw new PipelineException(ex);
        }
        contentHandler = handler;
        lexicalHandler = handler;
        handler.getTransformer().setOutputProperty("method", outputType);
        Result res = ctx.getResult();
        if (res instanceof StreamResult) {
            handler.setResult(res);
        } else {
            throw new PipelineException("Result type not supported");
        }
        
    }


    /**  Recycles unneeded objects */
    public void recycle() {
        super.recycle();
        handler = null;
    }


    /**
     *  Sets the output type to serialize as
     *
     *@param  type  "html", "xml", or "text
     */
    public void setOutputType(String type) {
        outputType = type;
    }

}

